package game;

import java.awt.*;

import javax.swing.*;

import java.awt.event.*;
import java.lang.Thread;
import java.util.ArrayList;

public class BreakoutPanel extends JPanel implements Runnable {
	
	private static final long serialVersionUID = -5077270860312119248L;
	Paddle p;
	Ball b;
	Brick[][] brick = new Brick[10][5];
	int balls = 3, bricksLeft = 50;
	Thread myThread;
	int xSpeed;
	ArrayList<Pill> pills = new ArrayList<Pill>();
	int waitTime;
	boolean suspendFlag;
	
	
	public BreakoutPanel(int width, int height){
		super.setSize(width, height);
		
		createBricks();
		
		p = new Paddle(width/2,height-(height/10),width/7,height/50,Color.BLACK);
		addMouseMotionListener(new PanelMotionListener());
		b = new Ball(getWidth()/2,getHeight()/2,getWidth()/100,Color.BLUE);
		
		
		waitTime = Integer.parseInt(JOptionPane.showInputDialog(null,
			"Enter a speed in milliseconds (recommended input is 25)",
			"Ball Speed?",
			JOptionPane.QUESTION_MESSAGE));
  			
		myThread = new Thread(this);
		suspendFlag = false;
		myThread.start();
		mysuspend();
		addMouseListener(new PanelListener());

	}
	
	public void createBricks(){
		int widthDistance = getWidth()/10;
		int heightDistance = getHeight()/20;
		boolean metal = true;
		for(int X = 0; X < 10; X++){
			for(int Y = 0; Y < 5; Y++){
				int random = (int)(Math.random()*13) + 1;
				if(random > 5 && random <= 13)
					random = 3;
				if(random == 4 || random == 5)
					random = 2;
				metal = (Y < 2);
				brick[X][Y] = new Brick(X*widthDistance,(heightDistance/2)+(Y*heightDistance),
					getWidth()/11,getHeight()/23,random,metal);
			}
		}
	}
  	
  	void mysuspend() {
        suspendFlag = true;
     }
     synchronized void myresume() {
        suspendFlag = false;
         notify();
     }

  	public void run(){
  		xSpeed = 1;
		while(true){
			synchronized(this) {
	            while(suspendFlag) {
	               try {
					wait();
				} catch (InterruptedException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
	            }
	          }
	        
			int x1 = b.getX();
			int y1 = b.getY();
			
			//adjust speed
			if (Math.abs(xSpeed) > 2){
				if(xSpeed > 2)
					xSpeed--;
				if(xSpeed < 2)
					xSpeed++;
			}

			checkPaddle(x1,y1);
			
			checkWall(x1,y1);
				
			checkBricks(x1,y1);
				
			checkLives();
		
			checkIfOut(y1);
			
			b.move();
			
			dropPills();
			
			checkPillList();
			
			repaint();
			try {
				Thread.sleep(waitTime);
			} catch (InterruptedException e ) {
				
			}
		}
	}
	


	public void placePill(Pill p){
		pills.add(p);
	}
	
	public void dropPills(){
		for(int i = 0; i < pills.size(); i++){
			Pill tempPill = pills.get(i);
			tempPill.drop();
			pills.set(i,tempPill);
		}
	}
	
	public void checkLives(){
		if(bricksLeft == 0){
			repaint();
			balls = 0;
			mysuspend();
		}
	}
	
	public void checkPillList(){
		for(int i = 0; i < pills.size(); i++){
			Pill tempPill = pills.get(i);
			if(p.absorbPill(tempPill)){
				pills.remove(i);
			}else if(tempPill.getY() > getHeight())
				pills.remove(i);
		}
	}
	
	public void checkPaddle(int x1, int y1){
			if(p.hitLeft(x1,y1)){
				b.setYDir(-2);
				xSpeed -= 1;
				b.setXDir(xSpeed);
			}else if(p.hitRight(x1,y1)){
				b.setYDir(-2);
				xSpeed += 1;
				b.setXDir(xSpeed);
			}
	}
	
	public void checkWall(int x1, int y1){
			if(x1 >= getWidth())
				xSpeed = -Math.abs(xSpeed);
				b.setXDir(xSpeed);
			if(x1 <= 0)
				xSpeed = Math.abs(xSpeed);
				b.setXDir(xSpeed);
			if(y1 <= 0)
				b.setYDir(2);
	}
	
    public void checkBricks(int x1, int y1){
    		for(int X = 0; X < 10; X++)
				for(int Y = 0; Y < 5; Y++){
					if(brick[X][Y].hitBottom(x1,y1)){
						b.setYDir(2);
						if(brick[X][Y].destroyed()){
							bricksLeft--;
							placePill(brick[X][Y].pill);
						}
					}
					if(brick[X][Y].hitLeft(x1,y1)){
						xSpeed = -xSpeed;
						b.setXDir(xSpeed);
						if(brick[X][Y].destroyed()){
							bricksLeft--;
							placePill(brick[X][Y].pill);
						}
					}
					if(brick[X][Y].hitRight(x1,y1)){
						xSpeed = -xSpeed;
						b.setXDir(xSpeed);
						if(brick[X][Y].destroyed()){
							bricksLeft--;
							placePill(brick[X][Y].pill);
						}
					}
					if(brick[X][Y].hitTop(x1,y1)){
						b.setYDir(-2);
						if(brick[X][Y].destroyed()){
							bricksLeft--;
							placePill(brick[X][Y].pill);
						}
					}
				}
    }
    
    public void checkIfOut(int y1){
    	if(y1 > p.getY() + 10){
			balls --;
			b.setY(getHeight()/2); 
			repaint();
			mysuspend();
		}
    }
    
    


	public void paintComponent(Graphics g){
		super.paintComponent(g);
		p.draw(g);
		b.draw(g);
		for(int X = 0; X < 10; X++)
			for(int Y = 0; Y < 5; Y++)
				brick[X][Y].draw(g);
		g.setColor(Color.BLACK);
		g.drawString("Balls left: " + Integer.toString(balls), getWidth() - (getWidth()/7), getHeight() - (getHeight()/10));
		
		for(Pill p: pills){
			p.draw(g);
		}
		
		if(balls == 0){
			int heightBorder = getHeight();
			int widthBorder = getWidth();
			g.setColor(Color.BLACK);
			g.fillRect(widthBorder, heightBorder, getWidth() - (2 * widthBorder), getHeight() - (2 * heightBorder ));
			g.setColor(Color.WHITE);
			g.drawString("Game Over, Click mouse to start over", getWidth()/5,getHeight()/2);
		}
		
		if(bricksLeft == 0){
			int heightBorder = getHeight();
			int widthBorder = getWidth();
			g.setColor(Color.BLACK);
			g.fillRect(widthBorder, heightBorder, getWidth() - (2 * widthBorder), getHeight() - (2 * heightBorder ));
			g.setColor(Color.WHITE);
			g.drawString("Congratulations! You Win!", getWidth()/5,getHeight()/2);
		}
		
	}
	
	private class PanelMotionListener extends MouseMotionAdapter{
		public void mouseMoved(MouseEvent e){
			int newX = e.getX()-getWidth()/17;
			p.setX(newX);
			repaint();
		}
	}
	private class PanelListener extends MouseAdapter{
		public void mousePressed(MouseEvent e){
			if(e.getButton() == MouseEvent.BUTTON1) {
			if (balls>0){
				myresume();
			}else{
				balls = 3;
				createBricks();
				for(int X = 0; X < 10; X++){
					for(int Y = 0; Y < 5; Y++){
						brick[X][Y].setVisible(true);
					}
				}
				b.setY(getHeight()/2);
				bricksLeft = 50;
				repaint();
				myresume();
			}
		} else {
			System.exit(1);
			
		}
	}
	}
}
